import { asyncRouterMap, constantRouterMap } from '@/router/index'

/**
 * 通过meta.role判断是否与当前用户权限匹配
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.role) {
    // some() 方法用于检测数组中的元素是否满足指定条件（函数提供）。
    // some() 方法会依次执行数组的每个元素：
    // 如果有一个元素满足条件，则表达式返回true , 剩余的元素不会再执行检测。
    // 如果没有满足条件的元素，则返回false。
    return roles.some(role => route.meta.role.indexOf(role) >= 0)
  } else {
    return true
  }
}

/**
 * 递归过滤异步路由表，返回符合用户角色权限的路由表
 * @param asyncRouterMap
 * @param roles
 */
function filterAsyncRouter(asyncRouterMap, roles) {
  // 对数组中的每个元素都执行一次指定的函数（callback），
  // 并且创建一个新的数组，该数组元素是所有回调函数执行时返回值为 true 的原数组元素。
  // 它只对数组中的非空元素执行指定的函数，没有赋值或者已经删除的元素将被忽略，
  // 同时，新创建的数组也不会包含这些元素。
  const accessedRouters = asyncRouterMap.filter(route => {
    if (hasPermission(roles, route)) {
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, roles)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      // concat 方法用于连接两个或多个数组
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    // 将符合用户权限的异步路由添加到路由表里
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { roles } = data
        let accessedRouters
        if (roles.indexOf('admin') >= 0) {
          accessedRouters = asyncRouterMap
        } else {
          accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
        }
        commit('SET_ROUTERS', accessedRouters)
        // 结束promise;
        resolve()
      })
    }
  }
}

export default permission
